package com.zzx.util;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;



/**
 * 
 * @ClassName: RSAsignature 
 * @Description: TODO(这里用一句话描述这个类的作用) 
 * @author zzx
 *
 * @date 2020年7月3日
 */
public class RSAsignature {
	private static final String PUBLIC_KEY = "publickey";
    private static final String PRIVATE_KEY = "privatekey";
 
    /*
     *RSA生成密钥对
     */
    public static Map<String,Object> GenerateKeyPair(String keyType, int keySize) throws Exception {
        KeyPairGenerator pairGenerator = KeyPairGenerator.getInstance(keyType);
        pairGenerator.initialize(keySize);
        //生成秘钥对
        KeyPair keyPair = pairGenerator.generateKeyPair();
        //获得公钥和私钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        Map<String,Object> map = new HashMap<String,Object>();
        map.put(PUBLIC_KEY,publicKey);
        map.put(PRIVATE_KEY,privateKey);
        return  map;
    }
    /*
    *从Map中获得密钥对
    */
    public static RSAPublicKey GetPublicKey(Map<String,Object> map){
        RSAPublicKey publicKey = (RSAPublicKey) map.get(PUBLIC_KEY);
        return publicKey;
    }
    public static RSAPrivateKey GetPrivateKey(Map<String,Object> map){
        RSAPrivateKey privateKey = (RSAPrivateKey) map.get(PRIVATE_KEY);
        return privateKey;
    }
    /*
	 * 	私钥对原始数据进行签名
	 */
	public static byte[] signature(String privateKey, byte[] data) throws Exception {
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(hexStringToBytes(privateKey));
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PrivateKey privateKey_new = keyFactory.generatePrivate(keySpec);

		Signature signature = Signature.getInstance("MD5withRSA");
		signature.initSign(privateKey_new);
		signature.update(data);
		return signature.sign();
	}

    /*
     * 	公钥、原始数据、原始签名数据进行验证
     */
	public static boolean verify(String publicKey, byte[] data, String sign) throws Exception {   
    	X509EncodedKeySpec keySpec = new X509EncodedKeySpec(hexStringToBytes(publicKey));
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PublicKey pKey = keyFactory.generatePublic(keySpec);
		
    	Signature signature = Signature.getInstance("MD5withRSA");
        signature.initVerify(pKey);
        signature.update(data);
        return signature.verify(hexStringToBytes(sign));
    }
 
    public static void main(String agrs[]) throws Exception {
    	// 获取private public 秘钥
		Map<String, Object> map = GenerateKeyPair("RSA", 2048);
		RSAPublicKey publicKey = RSAsignature.GetPublicKey(map);
		RSAPrivateKey privateKey = RSAsignature.GetPrivateKey(map);

		String privateKeyStr = fromBytesToHexString(privateKey.getEncoded());
		String publicKeyStr = fromBytesToHexString(publicKey.getEncoded());
		
    //			String privateKeyStr = "db469c5aa8797b25114c7c1434399d627d4ebcffebb36fb30f93c83139bc96c933d03f4bc837e05d6a4cd737f189c29cb8200d0a9de47aadd52c0df04f521ccc7d0672885a3379224c01bc55d4d35352d19ec2beec2ac871ca197eea53c9faf69e5eee8b6178bcde2dbe2a88d6ae8ea9c1871716fcd578d1af6cf90a11bd421925e8d5a407b208541b3b08f927c054a3dd73c7804fbb3e8e266121c0714bffc63fdc813b3cbff198a9a55c121f7ff9753e0c8a5710742e1cdebe33614d31c057a8b0cdef97d2fd835acb6320ff6e5d5f9ca814956cdcbf7fab5e9ed26e6938b198c553f3f209e6314945b1d9b9886fefcdecbacfabf6d8189e4ce4e83c3d0526fd4d19fb162532ec4f2a042641a28cb2478d95c501e83c9a30758bc2bd446fb99e6047f6f03bfd45109ff9937838704fb3278fbacb5140c35a431d83a97e7d7c57b371485b4c86befcba5392661fc19f505abf9a75f00d6392f80085eccb47a45ad5ee942aea5085111ba4ccf2fa6182cf062b62c0d574f13319a93aaa7fcc86f55e502c933a6e3706222dc6077e8b6b490f670766fac96e1857088986f55b10155c19f8296019d80544e46ff8d5b08ffabf5f53e51d4675de591a03c7a6ee46c53d5835e570d77f3ee9eecdc83e3120413c57de5f9cf2804116c7e33110b097cc60c0dbbc9f97cdbb2c2ea60bd5dce35b0e040dbc966ea89b3cdf62a1f0ca6f717aee2b06ba287ae4aaaf0871b70e5231adb770753e7f7d566e7c58cedeac5b1a76a3273acf7f005371a4106ffbfa526183b50a166cf69cbad215a2f668c1bd9a79a47896e77dfb197bc31ef6b8b5425b45927f8748b2958dae9e64f8bf4bbee53eb92eb8c2a9b69cc5c7b17d3ff9a3c95bffb44aaef01bf03d3032489514c30435cb6a09599d1d198d1a3f59b516be463605da671ec55047bf60431c031cf0979f7623a56c9999c268f724838b681518017aa816e0a60d653a17c24939ba8762f8748d9ee920a14b4b69a92845fb261d7c800df827a57101d983777d70d938608765f4b3069ab2c3e84768ea8a45f2b6cd08b85ab6dda31d8937239010c97bc6f29870778d0f25ce9efa51ad825fd5baeb9fb447a7223b92a4310a6caae8c6e9c341d2913c12b723b79140418aa3f74502481564896060eed284a41f868025035ea938acdac1289fa3c2a5ee515f00915de6b02e60fff6391d6a8cb091226cb4b6d49ff779854d23267fd1dc6a64127109e37e9b449da673909870c27abec6f6f218434c5f2a8a9c3a9a5c26966075e43d3595a2fe637f1c2be68089fbeda6bb61677a9888e4bd5bb5bd49c45bee069da2b1e7e618b0193cbbb34148c6eef7f506e2147a7e95ce3f8755ac09dbd9434b4f9465dcb70b2d33c4eb51e36648552cbda22276f277973d9f769a9d0a377a4ff346fbda8cfe8bdc79c967a87a9041d58c43bd1ca8212a0722b0f14dd6325a7f96e54b2da3bf64de57d027d3da5237f59fcf0e81f268441d6185f28ddb2ae62894c4db11dbfc664b1b51891e2b770cca5f1353b2e7c57399da0b43083b0414de4ead839aa40d9e822d7ee7bb4f2bd0a3c4fa6a6d15fa4801eb525a78c19b43fcdbc145dc8bf59bb8f7dda8b6adbdade06f85dc0e699e7e45dc761e95325b214b2cbe33d434eac1bbd87f9d29c519003d7285e2e3b3a73c7b3f3c72fb7870274f7a5d3f61e2876d000d475aa247e4ed0d6aa47c9b5c539f0b8f7502dbb6dcc657200f098717cf79afedffc412cf52dddb60bba500836ecc669b9e8fb75b7da43df7c2800fba5b04b661996c1fc38e649409b50105dcfe7568a159856e8bb8c88bf6c7041d37c44bf081a752303871d9ab28cf3ab1f238fc02d0108e95e42202d1c7346d8db69587e52416d6eccca5ac14f3eea8d0f4b86b03fecb3bebb256db88a135852b225aaf823e380d7004290a661c26aeafcf497f3cfa2a67e30f8ff295059cf83708f5499fbf49fdfe1d10701236faa06106e5f929bb87d55139be5b300f21fcff144a34491662acd03874d9042807a2060c13e7817df8090fe728d2ff90769094a44e10ad37071067a5b166e8cf968c283d5693afcff2705596067e373391428b3dde697132aba247597ed3b8c43aeca4efcb920635de9c42837064ad8d554be7641164beedb86a9b4eb1008b9fdcebfad8d3500404eebc3dc24255838895ce07dfc29a6b6fc5311f30d0b43517224acecfc9103d5db7fb3c9cc1f76566d4fe";
    	//		String publicKeyStr = "9706f42bee3cd5947b32225f31cd1898abaf81b782eb467b0c0a7ba64738edc493e05db9163723cbb7ade5fd32ae42c8c9d92c003299651170e643e5a58b932edbc0ddf0cf263c773f695a649e8e58a0c4e1dd9fe7ef05d347cea9477e5e0951efc5fb93302c71318ff4b95dc423a7e2e34df76ec36d838b0f079f5e8b374cd6136612e630425e9b91970a86661b2c5b88e28ec7dd3bd435cb959a8394090c4756b8c299dbffef6ae79e5f14583285769f4088ed49fc2efd4fb63bb5e3a16dd89f6e58806a498dd226d358ac5f188435cc37e46e2819c67c534a3cd917118b7a742c9571fe5009b38b697a13e53b7f885d06606ae4991d35ef79d04e92bd44a172afee7e28329711ef427e41fc4ae02829d72895b27a4c69ca105f8c3851ffd09859100a5bd915160dc9d58249d6837f7ee08fe198de8ef8f96564a899b6a38bfc712a635c656a29696b8073ed0ce8c7188d26dc358e52c8fb78f8c2d75c028677f0ccfabe8dba641fb4bfdfee1bf56aaca51d3a5509891e5ca66661e7e74159a115bc53a1b5c6db";
		
		System.out.println("私钥" + privateKeyStr);
		System.out.println("公钥" + publicKeyStr);
		// 测试验签
		Map<String,String> params = new HashMap<String,String>();
		params.put("name", "张三");
		params.put("sex", "3");

		byte[] signature = signature(privateKeyStr, params.toString().getBytes());
		String fromBytesToHexString = fromBytesToHexString(signature);
		System.out.println(fromBytesToHexString);
		System.out.println(getSign(params,"svTc1aoHWwI8S0aJjS30G05yVM4Kimik"));
		String s = getSign(params,"svTc1aoHWwI8S0aJjS30G05yVM4Kimik");
		boolean verify = verify(params.toString(), params.toString().getBytes(), s);
		System.out.println(verify);
		
    }
   
    public static String fromBytesToHexString(byte[] data) {
		StringBuilder str = new StringBuilder();
		for (int i = 0; i < data.length; i++) {
			String s = Integer.toHexString(0xFF & data[i]);
			if (s.length() == 1) {
				str.append(0).append(s);
			} else {
				str.append(s);
			}
		}
		return str.toString();
	}
    
    public static byte[] hexStringToBytes(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return null;
		}
		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d = new byte[length];
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));

		}
		return d;
	}

	private static byte charToByte(char c) {
		return (byte) "0123456789ABCDEFGH".indexOf(c);
	}
	
	public static String getSign(Map<String, String> params, String key) {
		//Map<String, String> paramsMap = new HashMap<String, String>();
		
		List<String> keys = new ArrayList<String>(params.keySet());
		Collections.sort(keys);
		String url = "";
		for (int i = 0; i < keys.size(); i++) {
			url += (i == 0 ? "" : "&") + keys.get(i) + "=" + params.get(keys.get(i));
		}
		url += "&key=" + key;
		return MD5Util.MD5Encode(url, "UTF-8").toUpperCase();
	}
	
	
}
